#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
from settings import DEBUG, DEFAULT_CAL_EXCHANGE
from dbpoolpy import init_pool, connect_db, settings, Insert, Update, Select, Delete
from constants import DB, DATABASES_POOL
from datetime import datetime, timedelta
import pandas as pd
from datasource import tushare_sdk as datasdk
from utils.format import d2id, id2d
from finta.finta import TA as ta
from . import selenium_chip as sc
from urllib3.exceptions import ReadTimeoutError
from requests.exceptions import ReadTimeout

settings.DB_TYPE = 'sqlite3'
# settings.DEBUG = DEBUG
settings.DEBUG = True
init_pool(DATABASES_POOL)

DEFAULT_DATA_LONG = 90
FRE_GRAP = 0.3

class Settor(object):
    def __init__(self, settor):
        self.settor = settor

    def where(self, **kwargs):
        self.settor.where(**kwargs).execute()


class BaseModel(object):
    @classmethod
    def select(cls, **kwargs):
        return Select(DB, cls.__table__)

    @classmethod
    def update(cls, **kwargs):
        return Update(DB, cls.__table__)

    @classmethod
    def insert(cls, **kwargs):
        return Insert(DB, cls.__table__)

    @classmethod
    def delete(cls, **kwargs):
        return Delete(DB, cls.__table__)

    @classmethod
    def find(cls, **kwargs):
        return Select(DB, cls.__table__).where(**kwargs).all()

    @classmethod
    def find_one(cls, **kwargs):
        return Select(DB, cls.__table__).where(**kwargs).first()

    @classmethod
    def get(cls, **kwargs):
        info = cls.find_one(**kwargs)
        assert info, "库(%s)表(%s)未找到对应信息(%s)" % (DB, cls.__table__, str(kwargs))
        return info

    @classmethod
    def select_page(cls, sql, **kwargs):
        with connect_db(DB) as db:
            return db.select_page(sql, **kwargs)

    @classmethod
    def add(cls, **kwargs):
        return Insert(DB, cls.__table__).values(**kwargs).execute()

    @classmethod
    def add_many(cls, many):
        cls.insert(many=many).execute()

    @classmethod
    def add_batch(cls, data, batch=2000):
        with connect_db(DB) as db:
            db.insert_batch(cls.__table__, data, batch)

    @classmethod
    def set(cls, **kwargs):
        return Settor(Update(DB, cls.__table__).values(**kwargs))

    @classmethod
    def rm(cls, **kwargs):
        return Delete(DB, cls.__table__).where(**kwargs).execute()

class UsersTB(BaseModel):
    __table__ = "users"

"""
mysql

CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(1024) DEFAULT NULL COMMENT '密码',
  `available` smallint(6) NOT NULL DEFAULT '1' COMMENT '状态：0：禁止 1：正常 2：待审核',
  `group_name` varchar(10) NOT NULL COMMENT '组名',
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_name` (`username`),
  UNIQUE KEY `users_email` (`email`),
  KEY `users_fk_group_name` (`group_name`),
  CONSTRAINT `users_fk_group_name` FOREIGN KEY (`group_name`) REFERENCES `users_group` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=150 DEFAULT CHARSET=utf8mb4

sqlite3

CREATE TABLE users (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  email varchar(50) DEFAULT NULL,
  username varchar(50) NOT NULL,
  password varchar(1024) DEFAULT NULL,
  available smallint(6) NOT NULL DEFAULT '1',
  group_name varchar(10) NOT NULL
);
CREATE UNIQUE INDEX username ON users(username);
CREATE UNIQUE INDEX users_email ON users(email);
"""

class GroupsTB(BaseModel):
    __table__ = "groups"

"""

mysql

CREATE TABLE `groups` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '组名',
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_group_un_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4

sqlite3

CREATE TABLE groups (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  name varchar(50) NOT NULL
);
CREATE UNIQUE INDEX users_un_name_idx ON groups(name);
"""


class DailyTB(BaseModel):
    __table__ = "daily"

    @staticmethod
    def _gen_start_and_end(ts_code, start_date, end_date):
        """获取缺失数据的开始时间和结束时间
        arg:ts_code, str, 股票号
        arg:start_date, datetime, 开始日期
        arg:end_date, datetime, 结束日期
        arg:exchange, int, 交易所, 默认是SSE
        """
        # cal_date_int = int(cal_date_int) if cal_date_int else d2id(datetime.now())
        # end_trade_cal = TradeCalTB.find_one(cal_date=cal_date_int, exchange=exchange)
        # end_date = id2d(end_trade_cal["pretrade_date"])
        # start_date = end_date - timedelta(days=DEFAULT_DATA_LONG)

        last_data = DailyTB.select().where(ts_code=ts_code).order_by("trade_date desc").first()
        first_data = DailyTB.select().where(ts_code=ts_code).order_by("trade_date").first()
        if not last_data or not first_data:
            return str(d2id(start_date)), str(d2id(end_date))
        last_trade_date = id2d(last_data["trade_date"])
        first_trade_date = id2d(first_data["trade_date"])
        if first_trade_date > end_date or last_trade_date < start_date:
            return str(d2id(start_date)), str(d2id(end_date))
        elif first_trade_date <= start_date and last_trade_date >= end_date:
            return None, None
        elif first_trade_date >= start_date and last_trade_date <= end_date:
            DailyTB.rm(ts_code=ts_code)
            return str(d2id(start_date)), str(d2id(end_date))
        elif first_trade_date <= start_date and last_trade_date < end_date:
            start_trade_cal = TradeCalTB.find_one(
                    pretrade_date=d2id(last_trade_date),
                    is_open=1,
                    exchange=DEFAULT_CAL_EXCHANGE)
            return str(start_trade_cal["cal_date"]), str(d2id(end_date))
        elif first_trade_date > start_date and last_trade_date >= end_date:
            end_trade_cal = TradeCalTB.find_one(cal_date=d2id(first_trade_date), exchange=DEFAULT_CAL_EXCHANGE)
            return str(d2id(start_date)), str(end_trade_cal["pretrade_date"])
        else:
            raise Exception("获取时间段错误")

    @classmethod
    def get_daily(cls, ts_code, cal_date_int=None, days=60):
        """取日交易历史数据"""
        # 取数据
        cal_date_int = int(cal_date_int) if cal_date_int else d2id(datetime.now())
        end_trade_cal = TradeCalTB.find_one(cal_date=cal_date_int, exchange=DEFAULT_CAL_EXCHANGE)
        end_date = id2d(end_trade_cal["pretrade_date"])
        start_datetime = end_date - timedelta(days=days)
        start_trade_cal = TradeCalTB.find_one(cal_date=d2id(start_datetime), exchange=DEFAULT_CAL_EXCHANGE)
        start_date = id2d(start_trade_cal["pretrade_date"])

        # 补全缺失的数据
        mis_start_date, mis_end_date = cls._gen_start_and_end(ts_code, start_date, end_date)
        if mis_start_date and mis_end_date:
            ee = None
            for n in range(3):
                try:
                    miss_daily = datasdk.get_daily(ts_code, mis_start_date, mis_end_date)
                    if not miss_daily.empty:
                        DailyTB.add_batch(miss_daily.to_dict(orient='records'))
                    time.sleep(FRE_GRAP)
                    break
                except Exception as e:
                    ee = e
                    print("重试:%s" % (n+1))
                    continue
            else:
                if ee is not None:
                    raise ee

        daily_data = DailyTB.select().where(
                trade_date=("between", [d2id(start_date), d2id(end_date)]),
                ts_code=ts_code
                ).order_by("trade_date").all()
        return daily_data


"""
mysql

CREATE TABLE `daily` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键自增',
  `ts_code` varchar(100) NOT NULL COMMENT '股票代码',
  `trade_date` varchar(100) NOT NULL COMMENT '交易日期',
  `open` float NOT NULL COMMENT '开盘价',
  `high` float NOT NULL COMMENT '最高价',
  `low` float NOT NULL COMMENT '最低价',
  `close` float NOT NULL COMMENT '收盘价',
  `pre_close` float NOT NULL COMMENT '昨日价',
  `change` float NOT NULL COMMENT '涨跌额',
  `pct_chg` float NOT NULL COMMENT '涨跌幅(未复权)',
  `vol` float NOT NULL COMMENT '成交量(手)',
  `amount` float NOT NULL COMMENT '成交额(千元)',
  PRIMARY KEY (`id`),
  KEY `daily_ts_code_IDX` (`ts_code`) USING BTREE,
  KEY `daily_trade_date_IDX` (`trade_date`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='日交易信息'


sqlite3

CREATE TABLE daily (
  id integer NOT NULL PRIMARY KEY autoincrement,
  ts_code varchar(100) NOT NULL,
  trade_date date NOT NULL,
  open float NOT NULL,
  high float NOT NULL,
  low float NOT NULL,
  close float NOT NULL,
  pre_close float NOT NULL,
  change float NOT NULL,
  pct_chg float NOT NULL,
  vol float NOT NULL,
  amount float NOT NULL
);
CREATE INDEX daily_trade_date_index ON daily(trade_date);
CREATE UNIQUE INDEX ts_code_trade_date_index ON daily(ts_code, trade_date)
"""

class StockTB(BaseModel):
    __table__ = "stock"

    @classmethod
    def get_stocks(cls):
        # 查看数据库是否存在数据
        """ 获取合理的股票
        CDR|1
        中小板|955
        主板|2029
        创业板|1080
        北交所|84
        科创板|386

        1: 不包含ST的
        2：主板
        """
        today = datetime.today()
        stocks = cls.find(name=("not like", "%ST%"), market="主板", cdate=d2id(today))
        if stocks:
            return stocks
        if not stocks:
            # 下载最新数据
            stocks_df = datasdk.get_all_stock()
            time.sleep(FRE_GRAP)
            if not stocks_df.empty:
                StockTB.rm()
                stocks_df["cdate"] = d2id(today)
                StockTB.add_batch(stocks_df.to_dict(orient='records'))
            # 取出不包含ST的主板
            stocks = cls.find(name=("not like", "%ST%"), market="主板")
            return stocks


"""
mysql

CREATE TABLE `stock` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `ts_code` varchar(100) NOT NULL COMMENT 'TS代码',
  `symbol` varchar(100) NOT NULL COMMENT '股票代码',
  `name` varchar(100) NOT NULL COMMENT '股票名称',
  `area` varchar(100) DEFAULT NULL COMMENT '地域',
  `industry` varchar(100) DEFAULT NULL COMMENT '所属行业',
  `market` varchar(100) DEFAULT NULL COMMENT '市场类型(主板/创业板/科创板/CDR)',
  `list_date` date NOT NULL COMMENT '上市日期',
  `cdate` date DEFAULT NULL COMMENT '数据创建日期',
  PRIMARY KEY (`id`),
  KEY `stock_symbol_IDX` (`symbol`) USING BTREE,
  KEY `stock_name_IDX` (`name`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='股票信息'

sqlite3

CREATE TABLE stock (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  ts_code varchar(100) NOT NULL,
  symbol varchar(100) NOT NULL,
  name varchar(100) NOT NULL,
  area varchar(100) DEFAULT NULL,
  industry varchar(100) DEFAULT NULL,
  market varchar(100) DEFAULT NULL,
  list_date date NOT NULL,
  cdate date DEFAULT NULL
);
CREATE UNIQUE INDEX stock_symbol_index ON stock(symbol);
CREATE INDEX stock_name_index ON stock(name);
"""

class IndicatorTB(BaseModel):
    __table__ = "indicator"

    @classmethod
    def get_stock_indicator(cls, ts_code, indicator, daily=None, **kwargs):
        if str(indicator).startswith('CHIP'):
            ind_func = getattr(sc, indicator, None)
            if ind_func is None:
                raise ValueError("not found the %s indictor in ta" % indicator)
            ind_df = ind_func(ts_code, **kwargs)
        else:
            if not daily:
                daily = DailyTB.get_daily(ts_code)
            daily_pd = pd.DataFrame(daily)
            ohlc = daily_pd[["open", "high", "low", "close", "vol"]].rename(columns={"vol": "volume"})
            ind_func = getattr(ta, indicator, None)
            if ind_func is None:
                raise ValueError("not found the %s indictor in ta" % indicator)
            ind_df = ind_func(ohlc, **kwargs)
        if isinstance(ind_df, pd.Series):
            return [ind_df.to_list()]
        elif isinstance(ind_df, pd.DataFrame):
            return list(ind_df.to_dict(orient="list").values())
        else:
            raise Exception("ta返回值类型错误")


"""
mysql

CREATE TABLE `indicator` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `abbr` varchar(100) NOT NULL COMMENT '指标常用的英文编写名称',
  `name` varchar(100) NOT NULL COMMENT '中文名称',
  `name_en` varchar(100) NOT NULL COMMENT '英文名称',
  `instruction` varchar(2048) NOT NULL COMMENT '说明',
  `direction` varchar(2048) DEFAULT NULL COMMENT '使用说明',
  `star` tinyint DEFAULT NULL COMMENT '指标评级',
  `available` tinyint DEFAULT 1 COMMENT '是否可用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `indicator_IDX` (`abbr`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='指标信息'

sqlite3

CREATE TABLE indicator (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  abbr varchar(100) NOT NULL,
  name varchar(100) NOT NULL,
  name_en varchar(100) NOT NULL,
  instruction varchar(100) NOT NULL,
  direction varchar(100) DEFAULT NULL,
  star tinyint DEFAULT NULL,
  available tinyint DEFAULT 1
);
CREATE UNIQUE INDEX addr_index ON indicator(abbr);

"""

class TriggerRecordTB(BaseModel):
    __table__ = "trigger_record"

"""
mysql

CREATE TABLE `trigger_record` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `strategy` varchar(100) NOT NULL COMMENT '策略名称',
  `addr` varchar(100) COMMENT '指标常用的英文编写名称',
  `ts_code` varchar(100) NOT NULL COMMENT '股票号',
  `orient` tinyint NOT NULL COMMENT '方向:1:买入,-1:卖出',
  `condition` varchar(200) COMMENT '触发条件',
  `trigger_date` date NOT NULL COMMENT '触发日期',
  PRIMARY KEY (`id`),
  KEY `strategy_IDX` (`strategy`) USEING BTREE,
  KEY `ts_code_IDX` (`ts_code`) USEING BTREE,
  KEY `trigger_date_IDX` (`trigger_date`) USEING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='触发记录'

sqlite3

CREATE TABLE trigger_record (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  strategy varchar(100) NOT NULL,
  addr varchar(100),
  ts_code varchar(100) NOT NULL,
  orient tinyint NOT NULL,
  condition varchar(200),
  trigger_date date NOT NULL
);
CREATE INDEX strategy_index ON trigger_record(strategy);
CREATE INDEX ts_code_index ON trigger_record(ts_code);
CREATE INDEX tigger_date_index ON trigger_record(trigger_date);
"""

class StrategyTB(BaseModel):
    __table__ = "strategy"


"""
mysql

CREATE TABLE `strategy` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `name` varchar(100) NOT NULL COMMENT '策略名称',
  `orient` tinyint NOT NULL COMMENT '方向:1:买入,-1:卖出',
  `condition` varchar(2000) NOT NULL COMMENT '触发条件',
  `available` smallint(6) NOT NULL DEFAULT '1' COMMENT '状态：0：禁止 1：正常,
  PRIMARY KEY (`id`),
  KEY `name_IDX` (`name`) USEING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='策略'

sqlite3

CREATE TABLE strategy (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  name varchar(100) NOT NULL,
  orient tinyint NOT NULL,
  condition varchar(2000) NOT NULL,
  available smallint(6) NOT NULL DEFAULT '1'
);
CREATE INDEX name_index ON strategy(name);
"""

class TradeCalTB(BaseModel):
    __table__ = "trade_cal"

    @classmethod
    def next_trade_day(cls, cal_date_int=None, exchange=DEFAULT_CAL_EXCHANGE):
        """获取计算日的上一个交易日的下一个交易日"""
        cal_date_int = cal_date_int if cal_date_int else d2id(datetime.now())
        cal = cls.find_one(cal_date=cal_date_int, exchange=exchange)
        if cal["is_open"] == 0:
            next_cal = cls.find_one(pretrade_date=cal["pretrade_date"], is_open=1, exchange=exchange)
            return next_cal["cal_date"]
        else:
            return cal_date_int

"""
mysql

CREATE TABLE `trade_cal` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `exchange` varchar(100) NOT NULL COMMENT '交易所',
  `cal_date` date NOT NULL COMMENT '交易日期',
  `is_open` tinyint NOT NULL COMMENT '是否交易',
  `pretrade_date` date NOT NULL COMMENT '上一个交易日',
  PRIMARY KEY (`id`),
  UNIQUE KEY `exchange_cal_date_IDX` (`exchange`, `cal_date`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='交易日历'

sqlite3

CREATE TABLE trade_cal (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  exchange varchar(100) NOT NULL,
  cal_date date NOT NULL,
  is_open tinyint NOT NULL,
  pretrade_date date NOT NULL
);
CREATE UNIQUE INDEX exchange_cal_date_idx ON trade_cal(cal_date, exchange);
CREATE INDEX pretrade_date_index ON trade_cal(pretrade_date);

"""

class Backtest(BaseModel):
    __table__ = "backtest"

"""
mysql

CREATE TABLE `backtest` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `strategy_name` varchar(100) NOT NULL COMMENT '策略名称',
  `params` varchar(1024) NOT NULL DEFAULT '' COMMENT '回测参数',
  `percent` int(11) NOT NULL DEFAULT 0 COMMENT '进度',
  `key1` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标1',
  `value1` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值1',
  `key2` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标2',
  `value2` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值2',
  `key3` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标3',
  `value3` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值3',
  `key4` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标4',
  `value4` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值4',
  `key5` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标5',
  `value5` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值5',
  `keys_bak` varchar(200) NOT NULL DEFAULT '' COMMENT '其他回测主要指标',
  `values_bak` varchar(200) NOT NULL DEFAULT '' COMMENT '其他回测指标值',
  `status` tinyint NOT NULL DEFAULT 0 COMMENT '状态：0:无状态，1:运行，2:成功，3:告警,4:报错',
  `pid` varchar(200) NOT NULL DEFAULT '' COMMENT '进程id',
  `mark` varchar(1024) NOT NULL DEFAULT '' COMMENT '回测其他结果',
  `cal_date` date NOT NULL COMMENT '回测日期',
  PRIMARY KEY (`id`),
  KEY `cls_date_idx` (`cal_date`) USEING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='回测表'

sqlite3

CREATE TABLE backtest (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  strategy_name varchar(100) NOT NULL,
  params varchar(1024) NOT NULL DEFAULT '',
  percent int(11) NOT NULL DEFAULT 0,
  key1 varchar(100) NOT NULL DEFAULT '',
  value1 varchar(100) NOT NULL DEFAULT '',
  key2 varchar(100) NOT NULL DEFAULT '',
  value2 varchar(100) NOT NULL DEFAULT '',
  key3 varchar(100) NOT NULL DEFAULT '',
  value3 varchar(100) NOT NULL DEFAULT '',
  key4 varchar(100) NOT NULL DEFAULT '',
  value4 varchar(100) NOT NULL DEFAULT '',
  key5 varchar(100) NOT NULL DEFAULT '',
  value5 varchar(100) NOT NULL DEFAULT '',
  keys_bak varchar(200) NOT NULL DEFAULT '',
  values_bak varchar(200) NOT NULL DEFAULT '',
  status tinyint NOT NULL DEFAULT 0,
  pid varchar(200) NOT NULL DEFAULT '',
  mark varchar(1024) NOT NULL DEFAULT '',
  cal_date date NOT NULL
);
CREATE INDEX cal_date_idx ON backtest(cal_date);

CREATE INDEX cal_date_idx ON backtest(cal_date);"""

class BacktestRecord(BaseModel):
    __table__ = "backtest_record"

"""
mysql

CREATE TABLE `backtest_record` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `backtest_id` int(11) NOT NULL COMMENT '回测表id',
  `stock_info` varchar(200) NOT NULL DEFAULT '' COMMENT '股票信息',
  `key1` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标1',
  `value1` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值1',
  `key2` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标2',
  `value2` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值2',
  `key3` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标3',
  `value3` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值3',
  `key4` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标4',
  `value4` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值4',
  `key5` varchar(100) NOT NULL DEFAULT '' COMMENT '回测主要指标5',
  `value5` varchar(100) NOT NULL DEFAULT '' COMMENT '回测指标值5',
  `keys_bak` varchar(200) NOT NULL DEFAULT '' COMMENT '其他回测主要指标',
  `values_bak` varchar(200) NOT NULL DEFAULT '' COMMENT '其他回测指标值',
  `mark` varchar(4096) NOT NULL DEFAULT '' COMMENT '回测其他结果',
  `cal_date` date NOT NULL COMMENT '回测日期',
  PRIMARY KEY (`id`),
  KEY `backtest_id_idx` (`backtest_id`) USEING BTREE,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='回测表'

sqlite3

CREATE TABLE backtest_record (
  id integer NOT NULL PRIMARY KEY AUTOINCREMENT,
  backtest_id int(11) NOT NULL,
  stock_info varchar(200) NOT NULL DEFAULT '',
  key1 varchar(100) NOT NULL DEFAULT '',
  value1 varchar(100) NOT NULL DEFAULT '',
  key2 varchar(100) NOT NULL DEFAULT '',
  value2 varchar(100) NOT NULL DEFAULT '',
  key3 varchar(100) NOT NULL DEFAULT '',
  value3 varchar(100) NOT NULL DEFAULT '',
  key4 varchar(100) NOT NULL DEFAULT '',
  value4 varchar(100) NOT NULL DEFAULT '',
  key5 varchar(100) NOT NULL DEFAULT '',
  value5 varchar(100) NOT NULL DEFAULT '',
  keys_bak varchar(200) NOT NULL DEFAULT '',
  values_bak varchar(200) NOT NULL DEFAULT '',
  mark varchar(4096) NOT NULL DEFAULT '',
  cal_date date NOT NULL
);
CREATE INDEX backtest_id_idx ON backtest_record(backtest_id);

"""
